//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Interop;
using System.Windows.Media;
using OpenLS.UI.Interfaces;


namespace OpenLS.UI
{
    static class WindowServices
    {
        public static T GetAncestor<T>(object sender)
        {
            DependencyObject d = sender as DependencyObject;
            while (d != null)
            {
                if (d is T)
                    return (T)(Object)d;
                d = VisualTreeHelper.GetParent(d);
            }
            return default(T);
        }
        public static IEnumerable<Visual> GetAncestors(Visual visual)
        {
            Visual d = (Visual) VisualTreeHelper.GetParent(visual);
            while (d != null)
            {
                yield return d;
                d = (Visual) VisualTreeHelper.GetParent(d);
            }
        }
        internal static IEnumerable<Visual> GetDescendants(Visual root)
        {
            yield return root;
            int count = VisualTreeHelper.GetChildrenCount(root);
            for (int i = 0; i < count; i++)
            {
                foreach (var item in GetDescendants((Visual) VisualTreeHelper.GetChild(root, i)))
                {
                    yield return item;
                }
            }
        }
        public static T GetAncestorUsingTemplatedParent<T>(object sender)
        {
            DependencyObject d = sender as DependencyObject;
            while (d != null)
            {
                if (d is T)
                    return (T)(Object)d;
                if (d is FrameworkElement && ((FrameworkElement)d).TemplatedParent is T)
                    return (T)(object)((FrameworkElement)d).TemplatedParent;
                d = VisualTreeHelper.GetParent(d);
            }
            return default(T);
        }

        /// <summary>
        /// Handler for dialog windows with Cancel and OK delegate event handlers.
        /// </summary>
        /// <param name="content"></param>
        /// <param name="title"></param>
        /// <param name="owner"></param>
        /// <param name="onOK"></param>
        /// <param name="onCancel"></param>
        public static void ShowDialogOkCancel<T>(T content, string title, UIElement owner, Action<object> onOK, Action<object> onCancel) where T: FrameworkElement, IDialogResultControl
        {
            Window modalDialogWindow = new Window();
            content.OnOkButtonClicked += (sender, args) =>
                {
                    onOK(content);
                    content_OnOkButtonClicked(sender, args);
                };
            content.OnCancelButtonClicked += (sender, args) =>
            {
                onCancel(content);
                content_OnOkButtonClicked(sender, args);
            };


            modalDialogWindow.WindowStyle = WindowStyle.None;
            modalDialogWindow.AllowsTransparency = true;
            modalDialogWindow.Title = title;
            modalDialogWindow.SizeToContent = SizeToContent.WidthAndHeight;
            modalDialogWindow.Content = content;
            modalDialogWindow.Resources.MergedDictionaries.Add(new DialogResources());
            modalDialogWindow.Owner = GetAncestor<Window>(owner);
            modalDialogWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            modalDialogWindow.Topmost = true;
            modalDialogWindow.ShowDialog();

        }

        static void content_OnCancelButtonClicked(object sender, EventArgs e)
        {
            var window = Window.GetWindow((sender as Control));
            if (window != null) window.Close();
        }

        static void content_OnOkButtonClicked(object sender, EventArgs e)
        {
            var window = Window.GetWindow((sender as Control));
            if (window != null) window.Close();
        }

        public static void ShowDialog<T>(T content, string title, UIElement owner, Action<object> onOK, Func<T, bool> HasError) where T : FrameworkElement
        {
            if (!BrowserInteropHelper.IsBrowserHosted)
            {
                var w = new DialogWindow { Title = title,  isDialog = true};
                w.FrontContent.Content = content;
                w.Resources.MergedDictionaries.Add(new DialogResources());
              //  ResourceDictionary d = new ResourceDictionary();
              //  d.Add(typeof (ComboBox), new ComboBoxResources()[Styles.RibbonComboBoxStyleKey]);
              //  w.Resources.MergedDictionaries.Add(d);
                w.Owner = GetAncestor<Window>(owner);
                w.Owner = GetAncestor<Window>(owner);
                // Set the dialog window validator, called before the OK/Cancel result is returned
                w.SetValidator(HasError);
                if (w.ShowDialog().GetValueOrDefault())
                {
                    if (!HasError(content))
                        onOK(null);
                }
            }
            else
            {
                var popup = new Popup();
                setupPopup(popup, owner, content);
                popup.Closed += (delegate { if (DialogResources.GetDialogResult(popup).GetValueOrDefault()) onOK(null); });
                popup.IsOpen = true;
            }
        }

        private static void setupPopup(Popup popup, UIElement owner, FrameworkElement toShow)
        {
            popup.Resources.MergedDictionaries.Add(new DialogResources());
            popup.Style = Styles.PopupDialogStyle;
            popup.PlacementTarget = owner;
            var b = new ContentControl
                        {
                            Template = PopupServiceResources.PopupContentControl
                        };
            popup.Child = b;
            b.Content = toShow;
            popup.Placement = PlacementMode.Center;
            b.Measure(new Size(1000, 1000));
            popup.Width = b.DesiredSize.Width;
            popup.Height = b.DesiredSize.Height;
        }

        public static void Show(FrameworkElement content, string title, UIElement owner)
        {
            if (!BrowserInteropHelper.IsBrowserHosted)
            {
                var w = new DialogWindow { Title = title, Content = content };
                w.Resources.MergedDictionaries.Add(new DialogResources());
                w.Owner = GetAncestor<Window>(owner);
                w.Show();

            }
            else
            {
                var popup = new Popup();
                setupPopup(popup,owner, content);
                popup.Resources.MergedDictionaries.Add(new DialogResources());
                popup.Style = Styles.PopupDialogStyle;
                popup.PlacementTarget = owner;
                var b = new ContentControl
                            {
                                Template = PopupServiceResources.PopupContentControl
                            };
                popup.Child = b;
                b.Content = content;
                popup.Placement = PlacementMode.Center;
                b.Measure(new Size(1000, 1000));
                popup.Width = b.DesiredSize.Width;
                popup.Height = b.DesiredSize.Height;
                popup.IsOpen = true;
            }
        }

        internal static void Close(FrameworkElement owned, bool? result)
        {
            if (BrowserInteropHelper.IsBrowserHosted)
            {
                GetAncestor<Popup>(owned).IsOpen = false; //\\ something for rcesult
            }
            else
            {
                var w = GetAncestor<Window>(owned);
                if (result != null)
                    w.DialogResult = result;
                w.Close();
            }
        }
        internal static Window GetOwnerWindow<T>(object sender) where T : FrameworkElement
        {
            if (BrowserInteropHelper.IsBrowserHosted)
                throw new NotImplementedException();
            var window = GetAncestor<Window>(sender);
            if (window != null)
                foreach (Window w in window.OwnedWindows)
                    if (w.Content is T)
                        return w;
            return null;
        }
    }
}
